package config

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

type Map struct {
	m map[string]string
}

// 没有所的map
func NewMap() *Map {
	m := new(Map)
	m.m = make(map[string]string)
	return m
}

func (m *Map) SetMap(mp map[string]string) {
	m.m = mp
	for k, v := range m.m {
		v1 := DecodeValue(v)
		if v1 != v {
			m.m[k] = v1
		}
	}
}

// Set 重设指定的Key Value
func (conf *Map) Set(key, val string) (err error) { //support section::key type in given key when using ini type.
	if len(key) == 0 {
		return errors.New("key is empty")
	}

	val = DecodeValue(val)

	conf.m[key] = val
	return
}

// String Get string value
func (conf *Map) String(key string) (s string) { //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
	s = conf.m[key]
	return
}

// Strings 没实现
func (conf *Map) Strings(key string) (ss []string) { //get string slice
	return
}

// Int Get int value by key
func (conf *Map) Int(key string) (int, error) {
	s := conf.m[key]
	return strconv.Atoi(s)
}

// Int64 Get int64 value by key
func (conf *Map) Int64(key string) (int64, error) {
	s := conf.m[key]
	return strconv.ParseInt(s, 10, 64)
}

// Bool Get bool value by key
func (conf *Map) Bool(key string) (bool, error) {
	s := conf.m[key]
	return ParseBool(s)
}

// Float Get float64 by key
func (conf *Map) Float(key string) (float64, error) {
	s := conf.m[key]
	return strconv.ParseFloat(s, 64)
}

// DefaultString Get value by key, if value is not exist, return defaultValue
func (conf *Map) DefaultString(key string, defaultVal string) string { // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
	s, ok := conf.m[key]
	if ok {
		if s == "" {
			return defaultVal
		}
		return s
	}
	return defaultVal
}

// DefaultStrings Not implementation
func (conf *Map) DefaultStrings(key string, defaultVal []string) []string {
	return nil
}

// DefaultInt Get int value by key, if value is not exist, return defaultValue
func (conf *Map) DefaultInt(key string, defaultVal int) int {
	i, err := conf.Int(key)
	if err != nil {
		return defaultVal
	}
	return i
}

// DefaultInt64 int64 value by key, if value is not exist, return defaultValue
func (conf *Map) DefaultInt64(key string, defaultVal int64) int64 {
	i, err := conf.Int64(key)
	if err != nil {
		return defaultVal
	}
	return i
}

// DefaultBool int64 value by key, if value is not exist, return defaultValue
func (conf *Map) DefaultBool(key string, defaultVal bool) bool {
	b, err := conf.Bool(key)
	if err != nil {
		return defaultVal
	}
	return b
}

// DefaultFloat float64 value by key, if value is not exist, return defaultValue
func (conf *Map) DefaultFloat(key string, defaultVal float64) float64 {
	f, err := conf.Float(key)
	if err != nil {
		return defaultVal
	}
	return f
}

// ParseBool 格式化布尔类型
func ParseBool(val any) (value bool, err error) {
	if val != nil {
		switch v := val.(type) {
		case bool:
			return v, nil
		case string:
			switch v {
			case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On":
				return true, nil
			case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
				return false, nil
			}
		case int8, int32, int64:
			strV := fmt.Sprintf("%s", v)
			if strV == "0" {
				return false, nil
			}
			return true, nil
		case float64:
			if v == 0 {
				return false, nil
			}
			return true, nil
		}
		return false, fmt.Errorf("parsing %q: invalid syntax", val)
	}
	return false, fmt.Errorf("parsing <nil>: invalid syntax")
}

func (conf *Map) ParseData(line string, dim string) (c Configer, err error) {
	s := strings.Split(line, dim)
	for _, v := range s {
		ss := strings.SplitN(v, "=", 2)
		if len(ss) == 2 {
			for i := range ss {
				ss[i] = strings.TrimSpace(ss[i])
			}
			if ss[0] == "" {
				continue
			}
			conf.m[ss[0]] = ss[1]
		}
	}
	return conf, nil
}
